package com.css.crm.bean;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.ResourceBundle;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.context.FacesContext;

import org.apache.log4j.Logger;

import com.css.crm.listener.JSFPerformanceLogger;
import com.css.crm.utility.ConstantUtil;
import com.css.crm.vo.AbstractObjectPermission;
import com.css.crm.vo.AbstractUser;
import com.css.crm.vo.MenuGroup;
import com.css.crm.vo.MenuItem;
import com.css.crm.vo.MenuMap;
import com.css.crm.vo.PermissionCollection;
import com.css.crm.vo.SystemMenu;
import com.css.crm.vo.UserManager;

/**
 * Implementation class for MeanBean to support menu display and selection
 */
@ManagedBean(name="menuBean")
@SessionScoped
public class MenuBean implements Serializable{
	
	private static final long serialVersionUID = 1L;
	private static final Logger log = Logger.getLogger(MenuBean.class);
	
	static ResourceBundle rb = ResourceBundle.getBundle("com.css.crm.config.ldap");
	public static final String LOGOUT = rb.getString("LOGOUT_REDIRECT_PAGE");
		
	//For status
	private MenuItem currentMenuItem;
	private String currentMenuItemId;

	//For display
	private List<MenuItem> userMenuItems;
	private List<MenuGroup> userMenuGroup;
	private List<MenuItem> accessPath;
	
	public MenuBean() {
		accessPath = MenuMap.menuMapInstance.getCurrentAccessPath(null);
		currentMenuItem = null;
		currentMenuItemId = MenuMap.menuMapInstance.getRtmuId();	
		
		//For Menu Item display
		userMenuItems = new ArrayList<MenuItem>();	
		
		FacesContext fc = FacesContext.getCurrentInstance();
		
		PermissionCollection pc = (PermissionCollection) fc.getApplication().getELResolver().getValue(fc.getELContext(), null, "permissionCollection");
			
		List<AbstractObjectPermission> pl = pc.getPermissionList();
		for (AbstractObjectPermission p : pl) {
			if (ConstantUtil.MENU_ITEM.equalsIgnoreCase(p.getType()) && (p.isReadable() || p.isWritable())) {
				if (getMenuItem(p.getObjectId()) != null) {
					userMenuItems.add(getMenuItem(p.getObjectId()));
				} else {
					log.info(p.getObjectId() + " not defined.");
				}
			}
		}
		
		userMenuGroup = new ArrayList<MenuGroup>();	
		
		log.debug(userMenuItems.size() + " menu items loaded.");			
		
		for (MenuItem mItem : userMenuItems){
			
			boolean groupExist = false;
			
			MenuGroup mg = getMenuGroup(mItem.getMenuId());
			
			for (MenuGroup umg : userMenuGroup){
				if (umg.getMugpId().equals(mg.getMugpId())){
					groupExist = true;
					umg.getMenuItemList().add(mItem);
					break;
				}
			}
			
			if (!groupExist){						
				ArrayList<MenuItem> mItemList = new ArrayList<MenuItem>();
				mItemList.add(mItem);
				mg.setMenuItemList(mItemList);						
				userMenuGroup.add(mg);
			}				
		}
		
		Collections.sort(userMenuGroup);
		for (MenuGroup umg : userMenuGroup){
			Collections.sort(umg.getMenuItemList());
		}
	}
	
	public ArrayList<SystemMenu> getTopMenuList(){
		return SystemMenu.systemMenuList;
	}
	
	public String getApplDispName(){
		return MenuMap.menuMapInstance.getApplDispName();
	}
	
	public String getRootMenuUrl(){
		return MenuMap.menuMapInstance.getRootUrl();
	}
	
	public MenuGroup getMenuGroup(String menuItemId){
		return MenuMap.menuMapInstance.getMenuGroup(menuItemId);
	}
	
	public MenuItem getMenuItem(String menuItemId){
		return MenuMap.menuMapInstance.getMenuItem(menuItemId);
	}
	
	public boolean isUserCanAccessMenuItem(String targetMenuItemId){
			    
	    for(MenuItem mItem : this.getUserMenuItems()){
	    	if(mItem.getMenuId().equals(targetMenuItemId)){
	    		return true;
	    	}
	    }	
	    
	    return false;
	}
	
	public MenuItem getCurrentMenuItem() {
		return currentMenuItem;
	}

	public void setCurrentMenuItem(MenuItem currentMenuItem) {
		this.currentMenuItem = currentMenuItem;
	}

	public List<MenuItem> getUserMenuItems() {
		return userMenuItems;
	}

	public void setUserMenuItems(List<MenuItem> userMenuItems) {
		this.userMenuItems = userMenuItems;
	}

	public List<MenuGroup> getUserMenuGroup() {
		return userMenuGroup;
	}

	public void setUserMenuGroup(List<MenuGroup> userMenuGroup) {
		this.userMenuGroup = userMenuGroup;
	}

	public List<MenuItem> getAccessPath() {
		return accessPath;
	}

	public void setAccessPath(List<MenuItem> accessPath) {
		this.accessPath = accessPath;
	}	
	/**
	 * Return size of access path
	 * 
	 * @return Integer that represents size of access path
	 */
	public int getAccessPathSize(){
		if ( this.accessPath != null ){
			return this.accessPath.size();
		} else {
			return 0;
		}
	}

	/**
	 * Reset Session
	 */
	public void resetBackingBeanSession() {
		Map<String, Object> beans = FacesContext.getCurrentInstance().getExternalContext().getSessionMap();
		Object[] s = beans.keySet().toArray();
		for (int i = 0; i < s.length; i++) {
			log.debug("Session " + s[i].toString());
			if (!s[i].toString().equals("user") && !s[i].toString().equals("permissionCollection") && !s[i].toString().equals("menuBean") && !JSFPerformanceLogger.isPhaseIdString(s[i].toString()))
				FacesContext.getCurrentInstance().getExternalContext().getSessionMap().remove(s[i]);
		}
	}
	
	public String logout() {	
		
		FacesContext fc = FacesContext.getCurrentInstance();
		AbstractUser user = (AbstractUser) fc.getApplication().getELResolver().getValue(fc.getELContext(), null, "user");
				
		UserManager userManager = (UserManager)fc.getApplication().getELResolver().getValue(fc.getELContext(), null, UserManager.BEAN_NAME);				
		log.info(user.getSessionId() + "|" + user.getId() + "|perform logout - start\n" + user);		
		if (userManager != null) {
			userManager.removeActiveTrack(user);
		}		
		Map<String, Object> beans = fc.getExternalContext().getSessionMap();
		Object[] s = beans.keySet().toArray();
		for (int i = 0; i < s.length; i++) {
			FacesContext.getCurrentInstance().getExternalContext().getSessionMap().remove(s[i]);
		}				
		
		//fc.getExternalContext().setRequest(null);
		
		log.info(user.getSessionId() + "|" + user.getId() + "|perform logout - end\n");			
		
		return LOGOUT;
	}
	
	public String getCurrentMenuItemId() {
		return currentMenuItemId;
	}

	public void setCurrentMenuItemId(String currentMenuItemId) {
		this.currentMenuItemId = currentMenuItemId;
	}

}
